{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6f4961db-8ba9-4328-aec9-0cab4ff7c6e3",
   "metadata": {},
   "source": [
    "Chapter 03\n",
    "\n",
    "# Python自定义函数计算矩阵乘法，列向量线性组合视角\n",
    "《线性代数》 | 鸢尾花书：数学不难"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29187c40-c535-418d-baa3-118917a6a47b",
   "metadata": {},
   "source": [
    "这段代码的核心目的是**用列向量的线性组合来重新诠释矩阵乘法的本质**，并实现了两个矩阵乘积的计算过程：$AB$ 和 $BA$。我们从数学角度来解释整个过程。\n",
    "\n",
    "---\n",
    "\n",
    "### 一、矩阵乘法的列向量解释\n",
    "\n",
    "我们知道，矩阵乘法 $C = AB$（设 $A$ 为 $m \\times p$ 矩阵，$B$ 为 $p \\times n$ 矩阵）可以从不同的角度理解：\n",
    "- 按 **行与列点积** 来看，$C_{ij}$ 是 $A$ 第 $i$ 行与 $B$ 第 $j$ 列的点积；\n",
    "- 本段代码采用的是另一种等价的思维方式：**列向量线性组合**。\n",
    "\n",
    "具体来说，我们将 $B$ 的每一列 $\\mathbf{b}_j$（$j = 1, \\dots, n$）作为一组**线性组合系数**，将其作用在矩阵 $A$ 的列向量上：\n",
    "$$\n",
    "C[:, j] = A \\cdot \\mathbf{b}_j = \\sum_{k=1}^p b_{kj} \\cdot A[:, k]\n",
    "$$\n",
    "\n",
    "也就是说，第 $j$ 列的结果是由 $A$ 的列向量 $\\{A[:, 1], \\dots, A[:, p]\\}$ 加权相加得到的。\n",
    "\n",
    "---\n",
    "\n",
    "### 二、函数解释：`col_LC`\n",
    "\n",
    "函数 `col_LC(A, coefficients)` 的数学含义是：\n",
    "\n",
    "> 给定一个矩阵 $A \\in \\mathbb{R}^{m \\times p}$ 和一个系数向量 $\\mathbf{c} \\in \\mathbb{R}^p$，输出向量\n",
    "$$\n",
    "\\mathbf{v} = \\sum_{k=1}^p c_k \\cdot \\mathbf{a}_k\n",
    "$$\n",
    "其中 $\\mathbf{a}_k = A[:, k]$ 是 $A$ 的第 $k$ 列。\n",
    "\n",
    "这是线性代数中最基础的线性组合的定义。\n",
    "\n",
    "---\n",
    "\n",
    "### 三、函数解释：`matrix_multiplication_col_LC`\n",
    "\n",
    "这个函数的目标是用线性组合的方法实现矩阵乘法 $C = AB$，其中：\n",
    "- $A \\in \\mathbb{R}^{m \\times p}$\n",
    "- $B \\in \\mathbb{R}^{p \\times n}$\n",
    "- 结果 $C \\in \\mathbb{R}^{m \\times n}$\n",
    "\n",
    "具体过程如下：\n",
    "\n",
    "对于 $j = 1$ 到 $n$：\n",
    "- 取出 $B$ 的第 $j$ 列 $\\mathbf{b}_j$\n",
    "- 用 $A$ 的列向量加权组合：\n",
    "$$\n",
    "C[:, j] = A \\cdot \\mathbf{b}_j = \\sum_{k=1}^p b_{kj} \\cdot A[:, k]\n",
    "$$\n",
    "\n",
    "这个思想把矩阵乘法分解为 **多个列向量组合问题**。\n",
    "\n",
    "---\n",
    "\n",
    "### 四、矩阵示例：$A$, $B = A^T$\n",
    "\n",
    "代码中具体的矩阵如下：\n",
    "\n",
    "$$\n",
    "A = \\begin{bmatrix}\n",
    "1 & 2 & 3 \\\\\n",
    "4 & 5 & 6\n",
    "\\end{bmatrix} \\in \\mathbb{R}^{2 \\times 3}\n",
    "$$\n",
    "\n",
    "则它的转置为：\n",
    "\n",
    "$$\n",
    "B = A^T = \\begin{bmatrix}\n",
    "1 & 4 \\\\\n",
    "2 & 5 \\\\\n",
    "3 & 6\n",
    "\\end{bmatrix} \\in \\mathbb{R}^{3 \\times 2}\n",
    "$$\n",
    "\n",
    "---\n",
    "\n",
    "### 五、计算 $AB$\n",
    "\n",
    "使用 `matrix_multiplication_col_LC(A, B)`，相当于计算：\n",
    "\n",
    "$$\n",
    "C = AB = \\begin{bmatrix}\n",
    "1 & 2 & 3 \\\\\n",
    "4 & 5 & 6\n",
    "\\end{bmatrix}\n",
    "\\begin{bmatrix}\n",
    "1 & 4 \\\\\n",
    "2 & 5 \\\\\n",
    "3 & 6\n",
    "\\end{bmatrix}\n",
    "= \n",
    "\\begin{bmatrix}\n",
    "14 & 32 \\\\\n",
    "32 & 77\n",
    "\\end{bmatrix}\n",
    "$$\n",
    "\n",
    "计算过程如下：\n",
    "\n",
    "- 第1列：$A$ 的列向量组合，权重为 $[1, 2, 3]$\n",
    "  $$\n",
    "  A[:,1]*1 + A[:,2]*2 + A[:,3]*3 =\n",
    "  \\begin{bmatrix} 1 \\\\ 4 \\end{bmatrix}*1 +\n",
    "  \\begin{bmatrix} 2 \\\\ 5 \\end{bmatrix}*2 +\n",
    "  \\begin{bmatrix} 3 \\\\ 6 \\end{bmatrix}*3 =\n",
    "  \\begin{bmatrix} 14 \\\\ 32 \\end{bmatrix}\n",
    "  $$\n",
    "\n",
    "- 第2列：权重为 $[4, 5, 6]$\n",
    "  $$\n",
    "  A[:,1]*4 + A[:,2]*5 + A[:,3]*6 =\n",
    "  \\begin{bmatrix} 32 \\\\ 77 \\end{bmatrix}\n",
    "  $$\n",
    "\n",
    "---\n",
    "\n",
    "### 六、计算 $BA$\n",
    "\n",
    "再看另一个方向的乘法 `matrix_multiplication_col_LC(B, A)` 相当于计算：\n",
    "\n",
    "$$\n",
    "BA = \\begin{bmatrix}\n",
    "1 & 4 \\\\\n",
    "2 & 5 \\\\\n",
    "3 & 6\n",
    "\\end{bmatrix}\n",
    "\\begin{bmatrix}\n",
    "1 & 2 & 3 \\\\\n",
    "4 & 5 & 6\n",
    "\\end{bmatrix}\n",
    "=\n",
    "\\begin{bmatrix}\n",
    "17 & 22 & 27 \\\\\n",
    "22 & 29 & 36 \\\\\n",
    "27 & 36 & 45\n",
    "\\end{bmatrix}\n",
    "$$\n",
    "\n",
    "计算原理同样是：把 $A$ 的列作为系数，作用于 $B$ 的列向量。\n",
    "\n",
    "---\n",
    "\n",
    "### 七、总结\n",
    "\n",
    "这段代码把经典的矩阵乘法公式\n",
    "$$\n",
    "C = AB \\quad\\text{其中 } C_{ij} = \\sum_{k=1}^p A_{ik} B_{kj}\n",
    "$$\n",
    "重新表达为**列向量线性组合的方式**：\n",
    "$$\n",
    "C[:, j] = \\sum_{k=1}^p B_{kj} \\cdot A[:, k]\n",
    "$$\n",
    "\n",
    "这种方式不仅加深对矩阵乘法本质的理解，还特别适合教学和理论推导（如在表示线性变换、特征空间、张量表示时）。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dff7a293-6adb-4c7f-adb2-00ab50aeba86",
   "metadata": {},
   "source": [
    "## 初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ec412391-b651-462c-88c5-85294e63f45f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bce13d47-8b03-4d7c-b066-9328bcfd3c7c",
   "metadata": {},
   "source": [
    "## 定义列向量线性组合函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e32e3c9d-8f25-4ed9-a902-451a09dcffe3",
   "metadata": {},
   "outputs": [],
   "source": [
    "def col_LC(A, coefficients):\n",
    "\n",
    "    m, p = A.shape\n",
    "    col_LC_result = np.zeros(m)  # 初始化组合结果\n",
    "    \n",
    "    for k in range(p):\n",
    "        col_LC_result += coefficients[k] * A[:, k]  \n",
    "        # A (左侧) 每列乘系数并相加\n",
    "    return col_LC_result"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2e8c0890-567a-4704-88a2-5b1d26810312",
   "metadata": {},
   "source": [
    "## 定义矩阵乘法函数，列向量组合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b2652127-4d1a-4eda-ac19-50e7b57ecb47",
   "metadata": {},
   "outputs": [],
   "source": [
    "def matrix_multiplication_col_LC(A, B):\n",
    "    # 获取矩阵 A 和 B 的形状\n",
    "    m, p_A = A.shape\n",
    "    p_B, n = B.shape\n",
    "\n",
    "    # 检测矩阵形状是否符合矩阵乘法规则\n",
    "    if p_A != p_B:\n",
    "        raise ValueError('Dimensions do not match')\n",
    "\n",
    "    # 初始化结果矩阵 C，形状 (m, n)，初始值设为 0\n",
    "    C = np.zeros((m, n))\n",
    "\n",
    "    for j in range(n):\n",
    "        coeffs = B[:, j]             \n",
    "        # 取出 B 的第 j 列，作为线性组合的系数\n",
    "        C[:, j] = col_LC(A, coeffs)  \n",
    "        # 计算 A 的列的线性组合\n",
    "    \n",
    "    return C"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb72ed03-83a6-44ab-b569-ebeb4458b45a",
   "metadata": {},
   "source": [
    "## 矩阵乘法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d67dd84b-6a10-4b97-8e64-84a4b58455f8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.array([[1, 2, 3],\n",
    "              [4, 5, 6]])\n",
    "A"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "2133b4b6-594a-4e3e-9c6a-1fd5b7fe7c5b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 4],\n",
       "       [2, 5],\n",
       "       [3, 6]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = A.T\n",
    "B"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b393e84-47be-460a-88e0-0f9b96b2d781",
   "metadata": {},
   "source": [
    "## 矩阵乘法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "2ccbf21f-326f-4aaf-bc11-1280266c824e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[14., 32.],\n",
       "       [32., 77.]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "matrix_multiplication_col_LC(A, B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "1f8478d4-a06c-45f5-9add-5fdcc2cd656c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[14, 32],\n",
       "       [32, 77]])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A @ B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "3c38ab38-2891-4b79-8a8a-723c6a4339f1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[17., 22., 27.],\n",
       "       [22., 29., 36.],\n",
       "       [27., 36., 45.]])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "matrix_multiplication_col_LC(B, A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4affb27e-14d5-4660-ae2b-204f22507827",
   "metadata": {},
   "outputs": [],
   "source": [
    "B @ A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7588bdb6-09d4-4fb0-be77-89a2b94eacd9",
   "metadata": {},
   "source": [
    "作者\t**生姜DrGinger**  \n",
    "脚本\t**生姜DrGinger**  \n",
    "视频\t**崔崔CuiCui**  \n",
    "开源资源\t[**GitHub**](https://github.com/Visualize-ML)  \n",
    "平台\t[**油管**](https://www.youtube.com/@DrGinger_Jiang)\t\t\n",
    "\t\t[**iris小课堂**](https://space.bilibili.com/3546865719052873)\t\t\n",
    "\t\t[**生姜DrGinger**](https://space.bilibili.com/513194466)  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:base] *",
   "language": "python",
   "name": "conda-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
